﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using iTFF.WPF.Resources.Languages;
using System.Windows.Input;
using iTFF.WPF.CP;
using System.ComponentModel;
using iTFF.WPF.Model.Artwork;
using System.Windows;
using System.Collections.ObjectModel;
using System.Collections.Specialized;

namespace iTFF.WPF.ViewModel
{
    class ArtworksViewModel : WorkspaceViewModel
    {
        #region Fields

        string _searchText;
        int _progessBarValue;
        ObservableCollection<ArtworkViewModel> _artworks;
        bool _isSearching;
        RelayCommand _fromiTunesCommand;
        RelayCommand _searchCommand;
        RelayCommand _cancelSearchCommand;
        BackgroundWorker _searchBW;

        #endregion

        #region Constructor

        public ArtworksViewModel()
        {
            base.DisplayName = Strings.Artworks;
            Artworks = new ObservableCollection<ArtworkViewModel>();
            Artworks.CollectionChanged += Artworks_CollectionChanged;
        }

        #endregion

        #region Collection management

        void Artworks_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.NewItems != null)
            {
                foreach (ArtworkViewModel item in e.NewItems)
                    item.PropertyChanged += OnArtworkPropertyChanged;
            }

            if (e.OldItems != null)
            {
                foreach (ArtworkViewModel item in e.OldItems)
                    item.PropertyChanged -= OnArtworkPropertyChanged;
            }
        }

        /// <summary>
        /// Updates IsApplyingNetwork
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void OnArtworkPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "IsApplyingArtwork")
            {
                // force property changed for all the artworks
                OnPropertyChanged("IsApplyingArtwork");
                foreach (var a in Artworks)
                    a.IsApplyingAnotherArtwork = ((ArtworkViewModel)sender).IsApplyingArtwork;
            }
        }

        #endregion

        #region Properties

        /// <summary>
        /// Gets the keywords for the search
        /// </summary>
        public string SearchText
        {
            get { return _searchText; }
            set
            {
                if (_searchText != value)
                {
                    _searchText = value;
                    OnPropertyChanged("SearchText");
                }
            }
        }

        /// <summary>
        /// Fetched artworks collection
        /// </summary>
        public ObservableCollection<ArtworkViewModel> Artworks
        {
            get { return _artworks; }
            set
            {
                if (_artworks != value)
                {
                    _artworks = value;
                    OnPropertyChanged("Artworks");
                }
            }
        }

        /// <summary>
        /// The progress bar value, from 0 to 100
        /// </summary>
        public int ProgressBarValue
        {
            get { return _progessBarValue; }
            set
            {
                if (_progessBarValue != value)
                {
                    _progessBarValue = value;
                    OnPropertyChanged("ProgressBarValue");
                }
            }
        }

        /// <summary>
        /// Gets or sets a value indicating if the windows is currently searching artworks
        /// </summary>
        public bool IsSearching
        {
            get { return _isSearching; }
            set
            {
                if (_isSearching != value)
                {
                    _isSearching = value;
                    OnPropertyChanged("IsSearching");
                }
            }
        }

        /// <summary>
        /// Indicates if one of the Artworks is currently applying artworks
        /// </summary>
        public bool IsApplyingArtwork
        {
            get { return Artworks.Any(a => a.IsApplyingArtwork); }
        }

        #endregion

        #region Settings properties

        public bool StoreMinimizedImage
        {
            get { return Settings.Default.ArtworkStoreMinimizedImage; }
            set
            {
                if (Settings.Default.ArtworkStoreMinimizedImage != value)
                {
                    Settings.Default.ArtworkStoreMinimizedImage = value;
                    OnPropertyChanged("StoreMinimizedImage");
                }
            }
        }

        public bool ApplyAlbums
        {
            get { return Settings.Default.ArtworkApplyAlbums; }
            set
            {
                if (Settings.Default.ArtworkApplyAlbums != value)
                {
                    Settings.Default.ArtworkApplyAlbums = value;
                    OnPropertyChanged("ArtworkApplyAlbums");
                }
            }
        }

        #endregion

        #region Commands

        /// <summary>
        /// Sets keyworkds from iTunes selection
        /// </summary>
        public ICommand FromiTunesCommand
        {
            get
            {
                if (_fromiTunesCommand == null)
                    _fromiTunesCommand = new RelayCommand(param => OnFromiTunesCommand(param));
                return _fromiTunesCommand;
            }
        }

        /// <summary>
        /// Sets keyworkds from iTunes selection
        /// </summary>
        /// <param name="param"></param>
        private void OnFromiTunesCommand(object param)
        {
            // use the first selected track
            var tracks = ControlPanel.Instance.iTunesControlPanel.SelectedTracks;
            if (tracks != null)
            {
                SearchText = string.Format("{0} {1}", tracks.First().Artist, tracks.First().Album);
                tracks.First();
            }
        }

        /// <summary>
        /// Searches the artworks
        /// </summary>
        public ICommand SearchCommand
        {
            get
            {
                if (_searchCommand == null)
                    _searchCommand = new RelayCommand(param => OnSearchCommand(param), param => !string.IsNullOrEmpty(SearchText));
                return _searchCommand;
            }
        }

        /// <summary>
        /// Cancels the search
        /// </summary>
        public ICommand CancelSearchCommand
        {
            get
            {
                if (_cancelSearchCommand == null)
                    _cancelSearchCommand = new RelayCommand(param => OnCancelSearchCommand(param));
                return _cancelSearchCommand;
            }
        }

        /// <summary>
        /// Cancels the search
        /// </summary>
        /// <param name="param"></param>
        private void OnCancelSearchCommand(object param)
        {
            _searchBW.CancelAsync();
            IsSearching = false;
        }

        #endregion

        #region Search

        /// <summary>
        /// Searches the artworks
        /// </summary>
        /// <param name="param"></param>
        private void OnSearchCommand(object param)
        {
            Artworks.Clear();

            // dispose the old BackgroundWorker
            if (_searchBW != null)
            {
                if (_searchBW.IsBusy)
                    _searchBW.CancelAsync();

                _searchBW.DoWork -= OnSearchBWDoWork;
                _searchBW.RunWorkerCompleted -= OnSearchBWRunWorkerCompleted;
            }

            // create the new one
            _searchBW = new BackgroundWorker() { WorkerSupportsCancellation = true };
            _searchBW.DoWork += OnSearchBWDoWork;
            _searchBW.RunWorkerCompleted += OnSearchBWRunWorkerCompleted;

            IsSearching = true;
            _searchBW.RunWorkerAsync();

        }

        void OnSearchBWDoWork(object sender, DoWorkEventArgs e)
        {
            var artworks = ControlPanel.Instance.ArtworksControlPanel.GetArtworks(_searchBW, SearchText);

            // if cancellation is pending, cancel it
            if (_searchBW.CancellationPending)
            {
                e.Cancel = true;
                return;
            }

            // add the artworks if any, without there images
            if (artworks == null)
                return;

            foreach (var a in artworks)
            {
                // use the ui thread
                ControlPanel.Instance.ExecuteActionWithUIThread(() => Artworks.Add(new ArtworkViewModel(a, this)));
            }

            e.Result = artworks;
        }

        void OnSearchBWRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                if (e.Error is ApplicationException)
                    ControlPanel.Instance.ShowError(e.Error);
                else
                    MessageBox.Show(string.Format(Strings.ArtworksViewModelSearchError, Environment.NewLine, e.Error.Message));
                IsSearching = false;
            }
            else if (!_searchBW.CancellationPending && !e.Cancelled)
            {
                IsSearching = false;

                // if nothing was found, notify the user
                if (e.Result == null)
                    ControlPanel.Instance.ShowBalloon(Strings.Sorry, iTFF.WinFormsWrappers.BalloonTipIcon.Info, Strings.ArtworksViewModelSearchNothingFound);
            }
        }

        #endregion

    }
}
